﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using GeneralLibs;

namespace Lists
{
    public class Phieu : DoiTuong
    {
        #region string Ma property
        public string Ma
        {
            get
            {
                if (_DataRow["Ma"] is string) return (string)_DataRow["Ma"];
                return "";
            }
            set
            {
                _DataRow["Ma"] = value;
            }
        }
        #endregion

        #region DateTime Ngay property
        public DateTime Ngay
        {
            get
            {
                return (DateTime)DataRow["Ngay"];
            }
            set
            {
                _DataRow["Ngay"] = value;
            }
        }
        #endregion

        #region string TinhTrangBenh property
        public string TinhTrangBenh
        {
            get
            {
                if (_DataRow["TinhTrangBenh"] is string) return (string)_DataRow["TinhTrangBenh"];
                return "";
            }
            set
            {
                _DataRow["TinhTrangBenh"] = value;
            }
        }
        #endregion

        #region Guid LoaiPhieuID property
        public Guid LoaiPhieuID
        {
            get
            {
                if (_DataRow["LoaiPhieuID"] is Guid) return (Guid)_DataRow["LoaiPhieuID"];
                return Guid.Empty;
            }
            set
            {
                _DataRow["LoaiPhieuID"] = value;
            }
        }
        #endregion

        #region Guid PhieuChaID property
        public Guid PhieuChaID
        {
            get
            {
                if (_DataRow["PhieuChaID"] is Guid) return (Guid)_DataRow["PhieuChaID"];
                return Guid.Empty;
            }
            set
            {
                _DataRow["PhieuChaID"] = value;
            }
        }
        #endregion

        #region Guid DichVuID property
        public Guid DichVuID
        {
            get
            {
                if (_DataRow["DichVuID"] is Guid) return (Guid)_DataRow["DichVuID"];
                return Guid.Empty;
            }
            set
            {
                _DataRow["DichVuID"] = value;
            }
        }
        #endregion

        #region Guid BenhNhanID property
        public Guid BenhNhanID
        {
            get
            {
                if (_DataRow["BenhNhanID"] is Guid) return (Guid)_DataRow["BenhNhanID"];
                return Guid.Empty;
            }
            set
            {
                _DataRow["BenhNhanID"] = value;
            }
        }
        #endregion

        #region string SoTheBHYT property
        public string SoTheBHYT
        {
            get
            {
                if (_DataRow["SoTheBHYT"] is string) return (string)_DataRow["SoTheBHYT"];
                return "";
            }
            set
            {
                _DataRow["SoTheBHYT"] = value;
            }
        }
        #endregion

        #region Guid BacSiID property
        public Guid BacSiID
        {
            get
            {
                if (_DataRow["BacSiID"] is Guid) return (Guid)_DataRow["BacSiID"];
                return Guid.Empty;
            }
            set
            {
                _DataRow["BacSiID"] = value;
            }
        }
        #endregion

        #region Guid ThuNganID property
        public Guid ThuNganID
        {
            get
            {
                if (_DataRow["ThuNganID"] is Guid) return (Guid)_DataRow["ThuNganID"];
                return Guid.Empty;
            }
            set
            {
                _DataRow["ThuNganID"] = value;
            }
        }
        #endregion

        #region Guid PhongBanID property
        public Guid PhongBanID
        {
            get
            {
                if (_DataRow["PhongBanID"] is Guid) return (Guid)_DataRow["PhongBanID"];
                return Guid.Empty;
            }
            set
            {
                _DataRow["PhongBanID"] = value;
            }
        }
        #endregion

        #region int SoThuTuKham property
        public int SoThuTuKham
        {
            get
            {
                if (_DataRow["SoThuTuKham"] is int) return (int)_DataRow["SoThuTuKham"];
                return 0;
            }
            set
            {
                _DataRow["SoThuTuKham"] = value;
            }
        }
        #endregion

        #region string GhiChu property
        public string GhiChu
        {
            get
            {
                if (_DataRow["GhiChu"] is string) return (string)_DataRow["GhiChu"];
                return "";
            }
            set
            {
                _DataRow["GhiChu"] = value;
            }
        }
        #endregion

        #region bool TaiKham property
        public bool TaiKham
        {
            get
            {
                if (DataRow["TaiKham"] is bool)
                    return (bool)DataRow["TaiKham"];
                else return false;
            }
            set
            {
                DataRow["TaiKham"] = value;
            }
        }
        #endregion

        #region decimal TienGiaLe property
        public decimal TienGiaLe
        {
            get
            {
                if (_DataRow["TienGiaLe"] is decimal) return (decimal)_DataRow["TienGiaLe"];
                return 0;
            }
            set
            {
                _DataRow["TienGiaLe"] = value;
            }
        }
        #endregion

        #region decimal PhanTramChietKhau property
        public decimal PhanTramChietKhau
        {
            get
            {
                if (_DataRow["PhanTramChietKhau"] is decimal) return (decimal)_DataRow["PhanTramChietKhau"];
                return 0;
            }
            set
            {
                _DataRow["PhanTramChietKhau"] = value;
            }
        }
        #endregion

        #region decimal TienChietKhau property
        public decimal TienChietKhau
        {
            get
            {
                if (_DataRow["TienChietKhau"] is decimal) return (decimal)_DataRow["TienChietKhau"];
                return 0;
            }
            set
            {
                _DataRow["TienChietKhau"] = value;
            }
        }
        #endregion

        #region decimal TienThanhToan property
        public decimal TienThanhToan
        {
            get
            {
                if (_DataRow["TienThanhToan"] is decimal) return (decimal)_DataRow["TienThanhToan"];
                return 0;
            }
            set
            {
                _DataRow["TienThanhToan"] = value;
            }
        }
        #endregion

        #region decimal TienKhachDua property
        public decimal TienKhachDua
        {
            get
            {
                if (_DataRow["TienKhachDua"] is decimal) return (decimal)_DataRow["TienKhachDua"];
                return 0;
            }
            set
            {
                _DataRow["TienKhachDua"] = value;
            }
        }
        #endregion

        #region decimal TienTraLai property
        public decimal TienTraLai
        {
            get
            {
                if (_DataRow["TienTraLai"] is decimal) return (decimal)_DataRow["TienTraLai"];
                return 0;
            }
            set
            {
                _DataRow["TienTraLai"] = value;
            }
        }
        #endregion

        #region bool CoBHYT property
        public bool CoBHYT
        {
            get
            {
                if (_DataRow["CoBHYT"] is bool) return (bool)_DataRow["CoBHYT"];
                return false;
            }
            set
            {
                _DataRow["CoBHYT"] = value;
            }
        }
        #endregion

        #region bool DaThuTien property
        public bool DaThuTien
        {
            get
            {
                if (DataRow["DaThuTien"] is bool)
                    return (bool)DataRow["DaThuTien"];
                else return false;
            }
            set
            {
                DataRow["DaThuTien"] = value;
            }
        }
        #endregion

        #region bool DaXuLy property
        public bool DaXuLy
        {
            get
            {
                if (_DataRow["DaXuLy"] is bool) return (bool)_DataRow["DaXuLy"];
                return false;
            }
            set
            {
                _DataRow["DaXuLy"] = value;
            }
        }
        #endregion

        #region int State property
        public int State
        {
            get
            {
                if (_DataRow["State"] is int) return (int)_DataRow["State"];
                return -1;
            }
            set
            {
                _DataRow["State"] = value;
            }
        }
        #endregion

        public Phieu(DataRow dataRow)
            : base(dataRow)
        {
        }

        public DanhMucKhoanMucPhieu _DanhSachKhoanMucClinic = new DanhMucKhoanMucPhieu();

        public void LoadKhoanMuc()
        {
            try
            {
                if (this == null) this.ID = Guid.Empty;
                _DanhSachKhoanMucClinic.LoadFromDB(this.ID);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }
    }

    public class DanhMucPhieu : DanhMucDoiTuong, IEnumerable
    {
        #region Instance property: Singleton Design pattern
        private static DanhMucPhieu _Instance;
        public static DanhMucPhieu Instance
        {
            get
            {
                if (_Instance == null)
                {
                    _Instance = new DanhMucPhieu();
                    _Instance.DataView = _Instance.DataTable.DefaultView;
                    try
                    {
                        UniqueConstraint uniqueConstraint = new UniqueConstraint(_Instance.DataTable.Columns["Ma"]);
                        _Instance.DataTable.Constraints.Add(uniqueConstraint);
                        _Instance.DataView.Sort = "Ma DESC";
                    }
                    catch (Exception ex)
                    {
                    }
                }
                return _Instance;
            }
        }
        #endregion

        #region override TableName property
        public override string TableName
        {
            get
            {
                return "Clinic_Phieu";
            }
        }
        #endregion

        #region Methods required by IEnumerable (use for foreach)
        public IEnumerator GetEnumerator()
        {
            return new TokenEnumerator(this);
        }

        private class TokenEnumerator : IEnumerator
        {
            private int _Position = -1;
            DanhMucDoiTuong _Dstk;

            public TokenEnumerator(DanhMucDoiTuong dstk)
            {
                _Dstk = dstk;
            }

            // Declare the MoveNext method required by IEnumerator:
            public bool MoveNext()
            {
                if (_Position < _Dstk.DataView.Count - 1)
                {
                    _Position++;
                    return true;
                }
                else
                {
                    return false;
                }
            }

            // Declare the Reset method required by IEnumerator:
            public void Reset()
            {
                _Position = -1;
            }

            // Declare the Current property required by IEnumerator:
            public object Current
            {
                get
                {
                    return new Phieu((_Dstk.DataView[_Position].Row));
                }
            }
        }
        #endregion

        public Phieu this[int index]
        {
            get
            {
                if (0 <= index && index <= this.Count)
                {
                    return new Phieu(DataTable.Rows[index]);
                }
                else
                {
                    return null;
                }
            }
        }

        public Phieu NewDoiTuong()
        {
            try
            {
                return new Phieu(Instance.DataTable.NewRow());
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public Phieu GetByProperty(string property, object value)
        {
            try
            {
                DataRow[] rows = GetDataRows(property, value);
                if (rows.Length > 0) return new Phieu(rows[0]);
                else return null;
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public Phieu GetByID(Guid objID)
        {
            try
            {
                return GetByProperty("ID", objID);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public Phieu GetByMa(string ma)
        {
            try
            {
                return GetByProperty("Ma", ma);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public DanhMucPhieu GetChuaThuTien(bool sinhTuDong)
        {
            try
            {
                //Nếu sinh phiếu thu mà LoadFromDB --> Các phiếu trên RAM bị lỗi hết
                if (!sinhTuDong)
                {
                    ChuanHoa_PhieuClinic_DaThuTienByChungTu();
                    LoadFromDB();
                }

                string condition = "DaThuTien = 0 OR DaThuTien IS NULL";
                return Filter(condition);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public static DanhMucPhieu GetAll()
        {
            try
            {
                return Instance;
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public DanhMucPhieu GetByLoaiPhieuID(Guid loaiPhieuID)
        {
            try
            {
                string filter = string.Format("LoaiPhieuID = '{0}'", loaiPhieuID);
                return Filter(filter);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public DanhMucPhieu GetByNhieuMaLoaiPhieu(List<string> maLoaiPhieus)
        {
            try
            {
                string condition = "";
                foreach (string maloai in maLoaiPhieus)
                {
                    LoaiPhieu loaiPhieu = DanhMucLoaiPhieu.Instance.GetByMa(maloai);
                    if (loaiPhieu != null)
                        condition += string.Format("LoaiPhieuID = '{0}' OR ", loaiPhieu.ID);
                }
                if (condition.EndsWith(" OR ")) condition = condition.Substring(0, condition.Length - 4);
                return Filter(condition);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public DanhMucPhieu GetListPhieuChiDinhByPhieuDangKiID(Guid phieuDKID)
        {
            try
            {
                string condition = string.Format("PhieuChaID = '{0}'", phieuDKID);
                return Filter(condition);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public DanhMucPhieu Filter(string filterExpression)
        {
            try
            {
                DanhMucPhieu obj = new DanhMucPhieu();
                obj.DataView = new DataView(DanhMucPhieu.Instance.DataTable, filterExpression, "Ngay DESC", DataViewRowState.CurrentRows);
                return obj;
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public void ChuanHoa_PhieuClinic_DaThuTienByChungTu()
        {
            SqlConnection con = new SqlConnection(GeneralLibs.LocalSettings.ConnectString);
            try
            {
                con.Open();
                SqlCommand cmd = con.CreateCommand();
                cmd.CommandText = string.Format("UPDATE Clinic_Phieu SET DaThuTien = 1 WHERE ID IN ( \n" +
                                                "SELECT B.ID FROM ChungTu A INNER JOIN Clinic_Phieu B ON A.Clinic_PhieuID = B.ID ) \n" +
                                                "AND (DaThuTien = 0 OR DaThuTien IS NULL) \n");
                cmd.ExecuteNonQuery();

                cmd.CommandText = string.Format("UPDATE Clinic_Phieu SET DaThuTien = 0 WHERE ID NOT IN ( \n" +
                                                "SELECT B.ID FROM ChungTu A INNER JOIN Clinic_Phieu B ON A.Clinic_PhieuID = B.ID ) \n" +
                                                "AND DaThuTien = 1 \n");
                cmd.ExecuteNonQuery();
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
            finally
            {
                con.Close();
            }
        }

        public void ChuanHoa_PhieuClinic_DaXuLyByHoSoKhamBenh()
        {
            SqlConnection con = new SqlConnection(GeneralLibs.LocalSettings.ConnectString);
            try
            {
                con.Open();
                SqlCommand cmd = con.CreateCommand();
                cmd.CommandText = string.Format("UPDATE Clinic_Phieu SET DaXuLy = 1 WHERE ID IN ( \n" +
                                                "SELECT A.ID FROM Clinic_Phieu A INNER JOIN Clinic_HoSoKhamBenh B ON A.ID = B.PhieuDangKiID ) \n" +
                                                "AND (DaXuLy = 0 OR DaXuLy IS NULL) \n");
                cmd.ExecuteNonQuery();

                cmd.CommandText = string.Format("UPDATE Clinic_Phieu SET DaXuLy = 0 WHERE ID NOT IN ( \n" +
                                                "SELECT A.ID FROM Clinic_Phieu A INNER JOIN Clinic_HoSoKhamBenh B ON A.ID = B.PhieuDangKiID ) \n" +
                                                "AND DaXuLy = 1 \n");
                cmd.ExecuteNonQuery();
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
            finally
            {
                con.Close();
            }
        }

        //Truy cập trực tiếp xuống DB
        public void GetPhieuDangKiHoacChiDinhTrucTiepTuDBByCondition(string whereCondition)
        {
            try
            {
                //Nếu sinh phiếu thu mà LoadFromDB --> Các phiếu trên RAM bị lỗi hết
                ChuanHoa_PhieuClinic_DaThuTienByChungTu();
                ChuanHoa_PhieuClinic_DaXuLyByHoSoKhamBenh();

                string query = string.Format("SELECT * FROM [{0}] \n" +
                                             "WHERE {1}",
                                             TableName, whereCondition);
                LoadFromDB(query);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public void GetPhieuDangKiHoacChiDinhTrucTiepTuDBByLoaiPhieuANDCondition(string maLoaiPhieu, string whereCondition)
        {
            try
            {
                //Nếu sinh phiếu thu mà LoadFromDB --> Các phiếu trên RAM bị lỗi hết
                ChuanHoa_PhieuClinic_DaThuTienByChungTu();
                ChuanHoa_PhieuClinic_DaXuLyByHoSoKhamBenh();

                string query = string.Format("SELECT * FROM Clinic_Phieu A INNER JOIN Clinic_LoaiPhieu B ON A.LoaiPhieuID = B.ID AND B.Ma = N'{0}' \n" +
                                             "WHERE {1}",
                                             maLoaiPhieu, whereCondition);
                LoadFromDB(query);
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public decimal GetDoanhSoByNgay(DateTime ngayXemBaoCao)
        {
            SqlConnection con = new SqlConnection(GeneralLibs.LocalSettings.ConnectString);
            try
            {
                con.Open();
                SqlCommand cmd = con.CreateCommand();
                cmd.CommandTimeout = GeneralLibs.Config.TimeOut;

                DateTime ngayBatDau = new DateTime(ngayXemBaoCao.Year, ngayXemBaoCao.Month, ngayXemBaoCao.Day, 00, 00, 01);
                DateTime ngayKetThuc = new DateTime(ngayXemBaoCao.Year, ngayXemBaoCao.Month, ngayXemBaoCao.Day, 23, 59, 59);

                cmd.CommandText = string.Format("SELECT SUM(TienThanhToan) TienThanhToan FROM [{0}] \n" +
                                             "WHERE  @ThoiDiemDau <= Ngay AND Ngay <= @ThoiDiemCuoi ",
                                             TableName);

                cmd.CommandType = CommandType.Text;
                cmd.Parameters.AddWithValue("@ThoiDiemDau", ngayBatDau);
                cmd.Parameters.AddWithValue("@ThoiDiemCuoi", ngayKetThuc);

                SqlDataAdapter da = new SqlDataAdapter(cmd);

                DataTable dt = new DataTable();
                da.Fill(dt);

                decimal result = 0;
                
                try 
	            {	        
	                result = CommonLib.ConvertToDecimal(dt.Rows[0]["TienThanhToan"]);
	            }
	            catch (Exception ex)
	            { }

                return result;
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        public void LoadFromDB(string query)
        {
            SqlConnection con = new SqlConnection(GeneralLibs.LocalSettings.ConnectString);
            try
            {
                con.Open();
                SqlCommand cmd = con.CreateCommand();
                LoadFromDB(cmd, query);
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
            finally
            {
                con.Close();
            }
        }
        public void LoadFromDB(SqlCommand cmd, string query)
        {
            try
            {
                cmd.CommandText = query;

                SqlDataAdapter da = new SqlDataAdapter(cmd);
                DataTable.Rows.Clear();
                da.Fill(DataTable);
                DataTable.AcceptChanges();
            }
            catch (SqlException sqlEx)
            {
                throw new CustomException(CustomException.GetSqlExceptionMessage(sqlEx));
            }
            catch (Exception ex)
            {
                if (ex is CustomException) throw ex;
                else
                {
                    throw new Exception(ex.Message);
                }
            }
        }
    }
}
